'use strict';
Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};
//字符串替换
String.method('deentityfy', function () {
    let entity = {
        quot: ':',
        lt: '<',
        gt: '>'
    };
    return function () {
        return this.replace(/&([^&;]+);/g,
            function (a, b) {
                let r = entity[b];
                return typeof r === 'string' ? r : a;
            }
        );
    };
}());
//document.writeln('&lt;&quot;&gt;'.deentityfy());
//序列号生成器
let serial_maker = function () {
    let prefix = '';
    let seq = 0;
    return {
        set_prefix: function (p) {
            prefix = String(p);
        },
        set_seq: function (s) {
            seq = s;
        },
        gensym: function () {
            let result = prefix + seq;
            seq += 1;
            return result;
        }
    };
};
let seqer = serial_maker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
let unique = seqer.gensym();
//document.writeln(unique);
//函数柯里化
Function.method('curry', function () {
    let slice = Array.prototype.slice,
        args = slice.apply(arguments),
        that = this;
    return function () {
        return that.apply(null, args.concat(slice.apply(arguments)));
    };
});
function add() {
    let sum = 0;
    for(let i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
let add1 = add.curry(1);
//document.writeln(add1(6));
//记忆
let memoizer = function (memo, formula) {
    let recur = function (n) {
        let result = memo[n];
        if (typeof result !== 'number') {
            result = formula(recur, n);
            memo[n] = result;
        }
        return result;
    };
    return recur;
};
let fibo1 = memoizer([0, 1], function (recur, n) {return recur(n-1) + recur(n-2);});
//document.writeln(fibo1(12));

let Mammal = function (name) {this.name = name;};
Mammal.prototype.get_name = function () {return this.name;};
Mammal.prototype.says = function () {return this.saying || '';};

Function.method('inherits', function (Parent) {
    this.prototype = new Parent();
    return this;
});

let Cat = function (name) {
    this.name = name;
    this.saying = 'meow';
}.inherits(Mammal)
    .method('purr', function (n) {
        let s = '';
        for (let i = 0; i < n; i++) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    })
    .method('get_name', function () {
        return this.says() + ' ' + this.name + ' ' + this.says();
    });
let myCat = new Cat('YuanQi');
document.writeln(myCat.says(), myCat.purr(5), myCat.get_name());
